import type { FC } from 'react';
import { message } from 'antd';
import type Konva from 'konva';
import { Stage, Layer, Rect } from 'react-konva';
import { useMemoizedFn, useSafeState } from 'ahooks';
import { useRef, useEffect, useMemo, memo } from 'react';
import type { GridType, PosType } from '../types';
import { getMousePosition, getMatrix } from './helper';

import styles from './styles.module.less';

type MouseContrlProps = {
  cols: number;
  rows: number;
  seatSize: number;
  onSelected?: (poinits: GridType[]) => any;
}

const MouseContrl: FC<MouseContrlProps> = (props) => {
  const { cols, rows, seatSize } = props;
  const ref = useRef<Konva.Stage>(null);
  const [endPos, setEndPos] = useSafeState<PosType | null>(null);
  const [startPos, setStartPos] = useSafeState<PosType | null>(null);

  const width = useMemo(() => {
    if (!startPos || !endPos) return;
    return endPos.x - startPos.x;
  }, [startPos, endPos]);

  const height = useMemo(() => {
    if (!startPos || !endPos) return;
    return endPos.y - startPos.y;
  }, [startPos, endPos]);

  const getContent = useMemoizedFn(() => {
    const stage = ref.current;
    return stage?.content as HTMLDivElement;
  });

  const isContains = useMemoizedFn((evt: MouseEvent) => {
    const content = getContent();
    const ele = evt.target as Element;
    return content.contains(ele);
  });

  const getPoint = useMemoizedFn((evt: MouseEvent) => {
    const content = getContent();
    return getMousePosition(content, evt)
  });

  const initContrl = useMemoizedFn(() => {
    const content = getContent();
    let flag: boolean = false;
    let endPos: PosType | null = null;
    let startPos: PosType | null = null;

    const clearMask = () => {
      setEndPos(endPos = null);
      setStartPos(startPos = null);
    }

    const onSelected = async () => {
      if (!startPos || !endPos) return;
      const poinits = getMatrix(startPos, endPos, seatSize);
      requestAnimationFrame(() => props.onSelected?.(poinits));
    }

    const onMouseMove = (evt: MouseEvent) => {
      if (flag) {
        evt.preventDefault();
        setEndPos(getPoint(evt));
      }
    }

    // 抬起鼠标
    const onMouseUp = (evt: MouseEvent) => {
      if (flag) {
        setEndPos(endPos = getPoint(evt));
        onSelected();
        clearMask();
      }
      flag = false;
    }

    //按下鼠标
    const onMouseDown = (evt: MouseEvent) => {
      if (flag = isContains(evt)) {
        setStartPos(startPos = getPoint(evt));
      }
    }

    document.addEventListener('mouseup', onMouseUp);
    content.addEventListener('mousemove', onMouseMove);
    document.addEventListener('mousedown', onMouseDown);
    document.addEventListener('contextmenu', onMouseUp);

    return () => {
      document.removeEventListener('mouseup', onMouseUp);
      content.removeEventListener('mousemove', onMouseMove);
      document.removeEventListener('mousedown', onMouseDown);
      document.removeEventListener('contextmenu', onMouseUp);
    }
  });

  useEffect(initContrl, [initContrl]);

  return (
    <Stage
      ref={ref}
      width={cols * seatSize}
      height={rows * seatSize}
      className={styles.mouse_contrl}
      style={{ top: seatSize, left: seatSize }}
    >
      <Layer>
        <Rect
          width={width}
          height={height}
          x={startPos?.x}
          y={startPos?.y}
          stroke='#666'
          strokeWidth={1}
          fill="rgba(0,0,0,.2)"
          visible={!!(startPos && endPos)}
        />
      </Layer>
    </Stage>
  );
}


export default memo(MouseContrl);

